/**
* @file memory.cpp
*
* Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All Rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include "runtime/acl_rt_impl.h"
#include "runtime/mem.h"
#include "runtime/rts/rts_mem.h"
#include "runtime/dev.h"
#include "runtime/rt_stars.h"
#include "runtime/kernel.h"
#include "log_inner.h"
#include "common_inner.h"
#include "error_codes_inner.h"
#include "utils/math_utils.h"
#include "toolchain/resource_statistics.h"

namespace {
static const std::map<aclDataType, rtDataType> kMapDataType = {
    { ACL_FLOAT, RT_DATA_TYPE_FP32 },
    { ACL_FLOAT16, RT_DATA_TYPE_FP16 },
    { ACL_INT16, RT_DATA_TYPE_INT16 },
    { ACL_INT4, RT_DATA_TYPE_INT4 },
    { ACL_INT8, RT_DATA_TYPE_INT8 },
    { ACL_INT32, RT_DATA_TYPE_INT32 },
    { ACL_BF16, RT_DATA_TYPE_BFP16 },
    { ACL_UINT8, RT_DATA_TYPE_UINT8 },
    { ACL_UINT16, RT_DATA_TYPE_UINT16 },
    { ACL_UINT32, RT_DATA_TYPE_UINT32 },
};

inline aclError MemcpyKindTranslate(const aclrtMemcpyKind kind, rtMemcpyKind_t &rtKind)
{
    switch (kind) {
        case ACL_MEMCPY_HOST_TO_DEVICE: {
            rtKind = RT_MEMCPY_HOST_TO_DEVICE;
            break;
        }
        case ACL_MEMCPY_DEVICE_TO_DEVICE: {
            rtKind = RT_MEMCPY_DEVICE_TO_DEVICE;
            break;
        }
        case ACL_MEMCPY_DEVICE_TO_HOST: {
            rtKind = RT_MEMCPY_DEVICE_TO_HOST;
            break;
        }
        case ACL_MEMCPY_HOST_TO_HOST: {
            rtKind = RT_MEMCPY_HOST_TO_HOST;
            break;
        }
        case ACL_MEMCPY_DEFAULT: {
            rtKind = RT_MEMCPY_DEFAULT;
            break;
        }
        default: {
            ACL_LOG_ERROR("[Check][MemcpyKindTranslate]param kind invalid, which is %d.", static_cast<int32_t>(kind));
            acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
                std::vector<std::string>({"param", "value", "reason"}),
                std::vector<std::string>({"kind", std::to_string(kind),
                "Memcpy kind should be ACL_MEMCPY_HOST_TO_DEVICE,"
                "ACL_MEMCPY_DEVICE_TO_DEVICE, ACL_MEMCPY_DEVICE_TO_HOST,"
                "ACL_MEMCPY_HOST_TO_HOST or ACL_MEMCPY_DEFAULT."}));
            return ACL_ERROR_INVALID_PARAM;
        }
    }
    return ACL_SUCCESS;
}

aclError CheckMemcpy2dParam(const void *const dst, const size_t dpitch, const void *const src, const size_t spitch,
    const size_t width, const size_t height, const aclrtMemcpyKind kind, rtMemcpyKind_t &rtKind)
{
    ACL_LOG_DEBUG("start to execute CheckMemcpy2dParam");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dst);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);
    ACL_REQUIRES_POSITIVE(height);
    ACL_REQUIRES_POSITIVE(width);

    if ((width > spitch) || (width > dpitch)) {
        ACL_LOG_ERROR("[Check][Width]input param width[%zu] must be smaller than spitch[%zu] and dpitch[%zu]",
            width, spitch, dpitch);
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
            std::vector<std::string>({"param", "value", "reason"}),
            std::vector<std::string>({"width", std::to_string(width), "must be smaller than spitch and dpitch"}));
        return ACL_ERROR_INVALID_PARAM;
    }

    switch (kind) {
        case ACL_MEMCPY_HOST_TO_DEVICE: {
            rtKind = RT_MEMCPY_HOST_TO_DEVICE;
            break;
        }
        case ACL_MEMCPY_DEVICE_TO_HOST: {
            rtKind = RT_MEMCPY_DEVICE_TO_HOST;
            break;
        }
        case ACL_MEMCPY_DEFAULT: {
            rtKind = RT_MEMCPY_DEFAULT;
            break;
        }
        default: {
            ACL_LOG_ERROR("[Check][Kind]invalid kind of memcpy, kind = %d", static_cast<int32_t>(kind));
            acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
                std::vector<std::string>({"param", "value", "reason"}),
                std::vector<std::string>({"kind", std::to_string(kind), "invalid kind of memcpy"}));
            return ACL_ERROR_INVALID_PARAM;
        }
    }
    return ACL_SUCCESS;
}
}

namespace acl {
aclError aclMallocMemInner(void **devPtr, const size_t size, bool isPadding,
                           const aclrtMemMallocPolicy policy, const uint16_t moduleId)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclMallocMemInner, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);
    // size must be greater than zero
    if (size == 0UL) {
        ACL_LOG_ERROR("malloc size must be greater than zero");
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
            std::vector<std::string>({"param", "value", "reason"}),
            std::vector<std::string>({"size", std::to_string(size), "size must be greater than zero"}));
        return ACL_ERROR_INVALID_PARAM;
    }
    size_t alignedSize;
    const bool huge1g = (policy == ACL_MEM_MALLOC_HUGE1G_ONLY) || (policy == ACL_MEM_MALLOC_HUGE1G_ONLY_P2P);
    isPadding = !huge1g && isPadding;
    ACL_REQUIRES_OK(acl::GetAlignedAndPaddingSize(size, isPadding, alignedSize));
    uint32_t flags = RT_MEMORY_DEFAULT;
    if (policy == ACL_MEM_MALLOC_HUGE_FIRST) {
        flags |= RT_MEMORY_POLICY_HUGE_PAGE_FIRST;
    } else if (policy == ACL_MEM_MALLOC_HUGE_ONLY) {
        flags |= RT_MEMORY_POLICY_HUGE_PAGE_ONLY;
    } else if (policy == ACL_MEM_MALLOC_NORMAL_ONLY) {
        flags |= RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
    } else if (policy == ACL_MEM_MALLOC_HUGE_FIRST_P2P) {
        flags |= RT_MEMORY_POLICY_HUGE_PAGE_FIRST_P2P;
    } else if (policy == ACL_MEM_MALLOC_HUGE_ONLY_P2P) {
        flags |= RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P;
    } else if (policy == ACL_MEM_MALLOC_NORMAL_ONLY_P2P) {
        flags |= RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P;
    } else if (policy == ACL_MEM_MALLOC_HUGE1G_ONLY) {
        flags |= RT_MEMORY_POLICY_HUGE1G_PAGE_ONLY;
    } else if (policy == ACL_MEM_MALLOC_HUGE1G_ONLY_P2P) {
        flags |= RT_MEMORY_POLICY_HUGE1G_PAGE_ONLY_P2P;
    } else {
        flags = RT_MEMORY_DEFAULT;
    }
    const rtError_t rtErr = rtMalloc(devPtr, alignedSize, flags, moduleId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("alloc device memory failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    return ACL_SUCCESS;
}

aclError aclrtMallocInnerWithCfg(void **devPtr, const size_t size, aclrtMemMallocPolicy policy, rtMallocAdvise advise,
    aclrtMallocConfig *cfg)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclrtMallocInnerWithCfg, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    // check attrs pointer
    if ((cfg != nullptr) && (cfg->numAttrs != 0) && (cfg->attrs == nullptr)) {
        ACL_LOG_ERROR("[Check][attrs]param must not be null when numAttrs is not 0.");
        acl::AclErrorLogManager::ReportInputError("EH0002", {"param"}, {"cfg"});
        return ACL_ERROR_INVALID_PARAM;
    }
    // size must be greater than zero
    if (size == 0UL) {
        ACL_LOG_ERROR("malloc size must be greater than zero");
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
            std::vector<std::string>({"param", "value", "reason"}),
            std::vector<std::string>({"size", std::to_string(size), "size must be greater than zero"}));
        return ACL_ERROR_INVALID_PARAM;
    }

    rtError_t rtErr = rtsMalloc(devPtr, size, static_cast<rtMallocPolicy>(policy), advise,
        reinterpret_cast<rtMallocConfig_t*>(cfg));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("alloc memory failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    return ACL_SUCCESS;
}
} // namespace acl

aclError aclrtMallocImpl(void **devPtr, size_t size, aclrtMemMallocPolicy policy)
{
    ACL_LOG_DEBUG("start to execute aclrtMalloc, size = %zu", size);
    return acl::aclMallocMemInner(devPtr, size, true, policy, acl::APP_MODE_ID_U16);
}

aclError aclrtMallocAlign32Impl(void **devPtr, size_t size, aclrtMemMallocPolicy policy)
{
    ACL_LOG_DEBUG("start to execute aclrtMallocAlign32, size = %zu", size);
    return acl::aclMallocMemInner(devPtr, size, false, policy, acl::APP_MODE_ID_U16);
}

aclError aclrtMallocCachedImpl(void **devPtr, size_t size, aclrtMemMallocPolicy policy)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclrtMallocCached, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    if (size == 0UL) {
        ACL_LOG_INNER_ERROR("malloc size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    size_t alignedSize;
    const bool huge1g = (policy == ACL_MEM_MALLOC_HUGE1G_ONLY) || (policy == ACL_MEM_MALLOC_HUGE1G_ONLY_P2P);
    const bool isPadding = !huge1g;
    ACL_REQUIRES_OK(acl::GetAlignedAndPaddingSize(size, isPadding, alignedSize));
    uint32_t cacheFlags = RT_MEMORY_DEFAULT;
    if (policy == ACL_MEM_MALLOC_HUGE_FIRST) {
        cacheFlags |= RT_MEMORY_POLICY_HUGE_PAGE_FIRST;
    } else if (policy == ACL_MEM_MALLOC_HUGE_ONLY) {
        cacheFlags |= RT_MEMORY_POLICY_HUGE_PAGE_ONLY;
    } else if (policy == ACL_MEM_MALLOC_NORMAL_ONLY) {
        cacheFlags |= RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
    } else if (policy == ACL_MEM_MALLOC_HUGE1G_ONLY) {
        cacheFlags |= RT_MEMORY_POLICY_HUGE1G_PAGE_ONLY;
    } else {
        cacheFlags = RT_MEMORY_DEFAULT;
    }
    const rtError_t rtErr = rtMallocCached(devPtr, alignedSize, cacheFlags, acl::APP_MODE_ID_U16);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("alloc device memory with cache failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    return ACL_SUCCESS;
}

aclError aclrtMallocWithCfgImpl(void **devPtr, size_t size, aclrtMemMallocPolicy policy, aclrtMallocConfig *cfg)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclrtMallocWithCfg, size = %zu", size);
    return acl::aclrtMallocInnerWithCfg(devPtr, size, policy, RT_MEM_ADVISE_NONE, cfg);
}

aclError aclrtMallocForTaskSchedulerImpl(void **devPtr, size_t size, aclrtMemMallocPolicy policy,
                                         aclrtMallocConfig *cfg)
{
    ACL_LOG_DEBUG("start to execute aclrtMallocForTaskScheduler, size = %zu", size);
    return acl::aclrtMallocInnerWithCfg(devPtr, size, policy, RT_MEM_ADVISE_TS, cfg);
}

aclError aclrtMallocHostWithCfgImpl(void **ptr, uint64_t size, aclrtMallocConfig *cfg)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclrtMallocHostWithCfg, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(ptr);
    // size must be greater than zero
    if (size == 0UL) {
        ACL_LOG_ERROR("malloc size must be greater than zero");
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
            std::vector<std::string>({"param", "value", "reason"}),
            std::vector<std::string>({"size", std::to_string(size), "size must be greater than zero"}));
        return ACL_ERROR_INVALID_PARAM;
    }
    const rtError_t rtErr = rtsMallocHost(ptr, size, reinterpret_cast<rtMallocConfig_t*>(cfg));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("alloc host memory with cfg failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    return ACL_SUCCESS;
}

aclError aclrtPointerGetAttributesImpl(const void *ptr, aclrtPtrAttributes *attributes)
{
    ACL_LOG_DEBUG("start to execute aclrtPointerGetAttributes");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(ptr);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(attributes);
    const rtError_t rtErr = rtsPointerGetAttributes(ptr, reinterpret_cast<rtPtrAttributes_t*>(attributes));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsPointerGetAttributes failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtHostRegisterImpl(void *ptr, uint64_t size, aclrtHostRegisterType type, void **devPtr)
{
    ACL_LOG_DEBUG("start to execute aclrtHostRegister");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(ptr);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);
    // size must be greater than zero
    if (size == 0UL) {
        ACL_LOG_ERROR("register size must be greater than zero");
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG,
            std::vector<std::string>({"param", "value", "reason"}),
            std::vector<std::string>({"size", std::to_string(size), "size must be greater than zero"}));
        return ACL_ERROR_INVALID_PARAM;
    }
    const rtError_t rtErr = rtsHostRegister(ptr, size, static_cast<rtHostRegisterType>(type), devPtr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsHostRegister failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtHostUnregisterImpl(void *ptr)
{
    ACL_LOG_DEBUG("start to execute aclrtHostUnregister");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(ptr);
    const rtError_t rtErr = rtsHostUnregister(ptr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsHostUnregister failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtMemFlushImpl(void *devPtr, size_t size)
{
    ACL_LOG_DEBUG("start to execute aclrtMemFlush, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    if (size == 0UL) {
        ACL_LOG_INNER_ERROR("flush cache size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    const rtError_t rtErr = rtFlushCache(devPtr, size);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("flush cache data to ddr failed, runtime result = %d, size = %zu",
            static_cast<int32_t>(rtErr), size);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtMemInvalidateImpl(void *devPtr, size_t size)
{
    ACL_LOG_INFO("start to execute aclrtMemInvalidate, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    if (size == 0UL) {
        ACL_LOG_INNER_ERROR("invalidate cache size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    const rtError_t rtErr = rtInvalidCache(devPtr, size);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("invalidate cache data failed, runtime result = %d, size = %zu",
            static_cast<int32_t>(rtErr), size);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtFreeImpl(void *devPtr)
{
    ACL_ADD_RELEASE_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    ACL_LOG_DEBUG("start to execute aclrtFree");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    const rtError_t rtErr = rtFree(devPtr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("free device memory failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_RELEASE_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE);
    return ACL_SUCCESS;
}

aclError aclrtMallocHostImpl(void **hostPtr, size_t size)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_HOST);
    ACL_LOG_DEBUG("start to execute aclrtMallocHost, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(hostPtr);
    // size must be greater than zero
    if (size == 0UL) {
        ACL_LOG_INNER_ERROR("malloc size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    const rtError_t rtErr = rtMallocHost(hostPtr, size, acl::APP_MODE_ID_U16);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("alloc host memory failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_HOST);
    return ACL_SUCCESS;
}

aclError aclrtFreeHostImpl(void *hostPtr)
{
    ACL_ADD_RELEASE_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_HOST);
    ACL_LOG_DEBUG("start to execute aclrtFreeHost");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(hostPtr);
    const rtError_t rtErr = rtFreeHost(hostPtr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("free host memory failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_RELEASE_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_HOST);
    return ACL_SUCCESS;
}

aclError aclrtMemcpyImpl(void *dst,
                         size_t destMax,
                         const void *src,
                         size_t count,
                         aclrtMemcpyKind kind)
{
    ACL_LOG_INFO("start to execute aclrtMemcpy, destMaxSize = %zu, srcSize = %zu, kind = %d",
        destMax, count, static_cast<int32_t>(kind));
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dst);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);

    rtMemcpyKind_t rtKind = RT_MEMCPY_RESERVED;
    const aclError ret = MemcpyKindTranslate(kind, rtKind);
    if (ret != ACL_SUCCESS) {
        ACL_LOG_INNER_ERROR("invalid kind of memcpy, kind = %d", static_cast<int32_t>(kind));
        return ret;
    }

    const rtError_t rtErr = rtMemcpy(dst, destMax, src, count, rtKind);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("synchronized memcpy failed, kind = %d, runtime result = %d",
            static_cast<int32_t>(kind), static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtMemsetImpl(void *devPtr, size_t maxCount, int32_t value, size_t count)
{
    ACL_LOG_DEBUG("start to execute aclrtMemset, maxSize = %zu, size = %zu, value = %d",
        maxCount, count, value);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    const rtError_t rtErr = rtMemset(devPtr, maxCount, static_cast<uint32_t>(value), count);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("set memory failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtMemcpyAsyncImpl(void *dst,
                              size_t destMax,
                              const void *src,
                              size_t count,
                              aclrtMemcpyKind kind,
                              aclrtStream stream)
{
    ACL_LOG_DEBUG("start to execute aclrtMemcpyAsync, destMaxSize = %zu, srcSize = %zu, kind = %d",
        destMax, count, static_cast<int32_t>(kind));
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dst);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);
    rtMemcpyKind_t rtKindVal = RT_MEMCPY_RESERVED;
    const aclError ret = MemcpyKindTranslate(kind, rtKindVal);
    if (ret != ACL_SUCCESS) {
        ACL_LOG_INNER_ERROR("invalid kind of memcpy, kind = %d", static_cast<int32_t>(kind));
        return ret;
    }

    ACL_REQUIRES_CALL_RTS_OK(rtMemcpyAsync(dst, destMax, src, count, rtKindVal, static_cast<rtStream_t>(stream)),
                             rtMemcpyAsync);
    return ACL_SUCCESS;
}

aclError aclrtMemcpyAsyncWithConditionImpl(void *dst,
                                           size_t destMax,
                                           const void *src,
                                           size_t count,
                                           aclrtMemcpyKind kind,
                                           aclrtStream stream)
{
    ACL_LOG_DEBUG("start to execute aclrtMemcpyAsyncWithCondition, destMaxSize = %zu, srcSize = %zu, kind = %d",
                  destMax, count, static_cast<int32_t>(kind));
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dst);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);
    rtMemcpyKind_t rtKindVal = RT_MEMCPY_RESERVED;
    const aclError ret = MemcpyKindTranslate(kind, rtKindVal);
    if (ret != ACL_SUCCESS) {
        ACL_LOG_INNER_ERROR("invalid kind of memcpy, kind = %d", static_cast<int32_t>(kind));
        return ret;
    }

    rtMemcpyAttributeValue_t memcpyAttrValue;
    // bit0 standing for not checking matching between address and kind, bit1 standing for checking page-locked addr
    memcpyAttrValue.checkBitmap = 0x00000002U;
    rtMemcpyAttribute_t memcpyAttr = {
        .id = RT_MEMCPY_ATTRIBUTE_CHECK,
        .value = memcpyAttrValue
    };
    rtMemcpyConfig_t memcpyConfig = {
        .attrs = &memcpyAttr,
        .numAttrs = 1U
    };

    ACL_REQUIRES_CALL_RTS_OK(rtMemcpyAsyncEx(dst, destMax, src, count, rtKindVal, static_cast<rtStream_t>(stream),
                             &memcpyConfig), rtMemcpyAsyncEx);
    return ACL_SUCCESS;
}

aclError aclrtMemsetAsyncImpl(void *devPtr, size_t maxCount, int32_t value, size_t count, aclrtStream stream)
{
    ACL_LOG_DEBUG("start to execute aclrtMemsetAsync, maxCount = %zu, value = %d, count = %zu",
        maxCount, value, count);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(devPtr);

    ACL_REQUIRES_CALL_RTS_OK(rtMemsetAsync(devPtr, maxCount, static_cast<uint32_t>(value), count, stream),
                             rtMemsetAsync);
    return ACL_SUCCESS;
}

aclError aclrtDeviceCanAccessPeerImpl(int32_t *canAccessPeer, int32_t deviceId, int32_t peerDeviceId)
{
    ACL_LOG_INFO("start to execute aclrtDeviceCanAccessPeer");

    if (deviceId == peerDeviceId) {
        ACL_LOG_INNER_ERROR("deviceId shouldn't be equal to peeerDeviceId");
        return ACL_ERROR_INVALID_PARAM;
    }

    uint32_t peerPhyId = 0U;
    rtError_t rtErr = rtGetDevicePhyIdByIndex(static_cast<uint32_t>(peerDeviceId), &peerPhyId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtGetDevicePhyIdByIndex failed, deviceId = %d, peerDeviceId = %d, "
            "runtime result = %d", deviceId, peerDeviceId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    rtErr = rtDeviceCanAccessPeer(canAccessPeer, static_cast<uint32_t>(deviceId), peerPhyId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtDeviceCanAccessPeer failed, deviceId = %d, peerPhyId = %u, "
            "runtime result = %d", deviceId, peerPhyId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    return ACL_SUCCESS;
}

aclError aclrtDeviceEnablePeerAccessImpl(int32_t peerDeviceId, uint32_t flags)
{
    ACL_LOG_INFO("start to execute aclrtDeviceEnablePeerAccess");

    if (flags != 0U) {
        ACL_LOG_INNER_ERROR("the flags must be 0, but current is %u", flags);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    int32_t deviceId = 0;
    rtError_t rtErr = rtGetDevice(&deviceId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtGetDevice failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    if (deviceId == peerDeviceId) {
        ACL_LOG_INNER_ERROR("deviceId shouldn't be equal to peeerDeviceId, deviceId = %d, peerDeviceId = %d",
            deviceId, peerDeviceId);
        return ACL_ERROR_INVALID_PARAM;
    }

    uint32_t peerPhyId = 0U;
    rtErr = rtGetDevicePhyIdByIndex(static_cast<uint32_t>(peerDeviceId), &peerPhyId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtGetDevicePhyIdByIndex failed, peerDeviceId = %d, runtime result = %d",
            peerDeviceId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    rtErr = rtEnableP2P(static_cast<uint32_t>(deviceId), peerPhyId, flags);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtEnableP2P failed, deviceId = %d, peerPhyId = %u, runtime result = %d",
            deviceId, peerPhyId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    return ACL_SUCCESS;
}

aclError aclrtDeviceDisablePeerAccessImpl(int32_t peerDeviceId)
{
    ACL_LOG_INFO("start to execute aclrtDeviceDisablePeerAccess");

    int32_t deviceId = 0;
    rtError_t rtErr = rtGetDevice(&deviceId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtGetDevice failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    if (deviceId == peerDeviceId) {
        ACL_LOG_INNER_ERROR("deviceId shouldn't be equal to peeerDeviceId, deviceId = %d, peerDeviceId = %d",
            deviceId, peerDeviceId);
        return ACL_ERROR_INVALID_PARAM;
    }

    uint32_t peerPhyId = 0U;
    rtErr = rtGetDevicePhyIdByIndex(static_cast<uint32_t>(peerDeviceId), &peerPhyId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtGetDevicePhyIdByIndex failed, peerDeviceId = %u, runtime result = %d",
            peerDeviceId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    rtErr = rtDisableP2P(static_cast<uint32_t>(deviceId), peerPhyId);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtDisableP2P failed, deviceId = %d, peerPhyId = %u, runtime result = %d",
            deviceId, peerPhyId, static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    return ACL_SUCCESS;
}

aclError aclrtGetMemInfoImpl(aclrtMemAttr attr, size_t *free, size_t *total)
{
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(free);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(total);
    ACL_LOG_DEBUG("start to execute aclrtGetMemInfo, memory attribute = %d", static_cast<int32_t>(attr));

    const rtError_t rtErr = rtMemGetInfoEx(static_cast<rtMemInfoType_t>(attr), free, total);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("get memory information failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    ACL_LOG_DEBUG("successfully execute aclrtGetMemInfo, memory attribute = %d, free memory = %zu bytes, "
        "total memory = %zu bytes", static_cast<int32_t>(attr), *free, *total);
    return ACL_SUCCESS;
}

aclError aclrtMemcpy2dImpl(void *dst,
                           size_t dpitch,
                           const void *src,
                           size_t spitch,
                           size_t width,
                           size_t height,
                           aclrtMemcpyKind kind)
{
    ACL_LOG_DEBUG("start to execute aclrtMemcpy2d, dpitch = %zu, spitch = %zu, width = %zu, height = %zu, kind = %d",
        dpitch, spitch, width, height, static_cast<int32_t>(kind));

    rtMemcpyKind_t rtKind = RT_MEMCPY_RESERVED;
    const aclError ret = CheckMemcpy2dParam(dst, dpitch, src, spitch, width, height, kind, rtKind);
    if (ret != ACL_SUCCESS) {
        return ret;
    }

    const rtError_t rtErr = rtMemcpy2d(dst, dpitch, src, spitch, width, height, rtKind);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("[Synchronized][Memcpy]synchronized memcpy failed, kind = %d, runtime result = %d",
            static_cast<int32_t>(kind), static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }

    ACL_LOG_DEBUG("Successfuly execute aclrtMemcpy2d, dpitch = %zu, spitch = %zu, width = %zu, height = %zu, "
        "kind = %d", dpitch, spitch, width, height, static_cast<int32_t>(kind));
    return ACL_SUCCESS;
}

aclError aclrtMemcpy2dAsyncImpl(void *dst,
                                size_t dpitch,
                                const void *src,
                                size_t spitch,
                                size_t width,
                                size_t height,
                                aclrtMemcpyKind kind,
                                aclrtStream stream)
{
    ACL_LOG_DEBUG("start to execute aclrtMemcpy2dAsync, dpitch = %zu, spitch = %zu, width = %zu, height = %zu,"
        " kind = %d", dpitch, spitch, width, height, static_cast<int32_t>(kind));

    rtMemcpyKind_t rtKindVal = RT_MEMCPY_RESERVED;
    const aclError ret = CheckMemcpy2dParam(dst, dpitch, src, spitch, width, height, kind, rtKindVal);
    if (ret != ACL_SUCCESS) {
        return ret;
    }

    ACL_REQUIRES_CALL_RTS_OK(rtMemcpy2dAsync(dst, dpitch, src, spitch, width, height, rtKindVal, stream),
                             rtMemcpy2dAsync);

    ACL_LOG_DEBUG("Successfuly execute aclrtMemcpy2dAsync, dpitch = %zu, spitch = %zu, width = %zu, height = %zu, "
        "kind = %d", dpitch, spitch, width, height, static_cast<int32_t>(kind));
    return ACL_SUCCESS;
}

aclError aclrtReserveMemAddressImpl(void **virPtr,
                                    size_t size,
                                    size_t alignment,
                                    void *expectPtr,
                                    uint64_t flags)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_RESERVE_RELEASE_MEMORY_ADDRESS);
    ACL_LOG_DEBUG("start to execute aclrtReserveMemAddress, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(virPtr);

    if (size == 0UL) {
        ACL_LOG_ERROR("reserve size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    if (expectPtr != nullptr) {
        ACL_LOG_ERROR("expectPtr must be nullptr");
        return ACL_ERROR_INVALID_PARAM;
    }
    if ((flags != 1ULL) && (flags != 0ULL)) {
        ACL_LOG_ERROR("flags of page type must be 0 or 1");
        return ACL_ERROR_INVALID_PARAM;
    }

    const rtError_t rtErr = rtReserveMemAddress(virPtr, size, alignment, expectPtr, flags);
    if (rtErr != RT_ERROR_NONE) {
        if (rtErr == ACL_ERROR_RT_FEATURE_NOT_SUPPORT) {
            ACL_LOG_WARN("reserve memory address unsupport, runtime result = %d", static_cast<int32_t>(rtErr));
        } else {
            ACL_LOG_CALL_ERROR("reserve memory address failed, runtime result = %d", static_cast<int32_t>(rtErr));
        }   
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_RESERVE_RELEASE_MEMORY_ADDRESS);
    return ACL_SUCCESS;
}

aclError aclrtReleaseMemAddressImpl(void *virPtr)
{
    ACL_ADD_RELEASE_TOTAL_COUNT(acl::ACL_STATISTICS_RESERVE_RELEASE_MEMORY_ADDRESS);
    ACL_LOG_DEBUG("start to execute aclrtReleaseMemAddress");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(virPtr);

    const rtError_t rtErr = rtReleaseMemAddress(virPtr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("release memory address failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_RELEASE_SUCCESS_COUNT(acl::ACL_STATISTICS_RESERVE_RELEASE_MEMORY_ADDRESS);
    return ACL_SUCCESS;
}

aclError aclrtMallocPhysicalImpl(aclrtDrvMemHandle *handle,
                                 size_t size,
                                 const aclrtPhysicalMemProp *prop,
                                 uint64_t flags)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_PHYSICAL_MEMORY);
    ACL_LOG_DEBUG("start to execute aclrtMallocPhysical, size = %zu", size);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(handle);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(prop);
    ACL_CHECK_WITH_MESSAGE_AND_RETURN(size != 0UL, ACL_ERROR_INVALID_PARAM,
                                      "malloc size must be greater than zero");
    ACL_CHECK_WITH_MESSAGE_AND_RETURN(flags == 0UL, ACL_ERROR_INVALID_PARAM,
                                      "flags must be 0");
    ACL_CHECK_WITH_MESSAGE_AND_RETURN(prop->handleType == ACL_MEM_HANDLE_TYPE_NONE,
                                      ACL_ERROR_INVALID_PARAM, "handleType must be ACL_MEM_HANDLE_TYPE_NONE");
    ACL_CHECK_WITH_MESSAGE_AND_RETURN(prop->allocationType == ACL_MEM_ALLOCATION_TYPE_PINNED,
                                      ACL_ERROR_INVALID_PARAM,
                                      "allocationType must be ACL_MEM_ALLOCATION_TYPE_PINNED");

    rtDrvMemProp_t rtProp = {};
    rtProp.side = prop->location.type;
    rtProp.devid = prop->location.id;
    rtProp.module_id = acl::APP_MODE_ID_U16;
    rtProp.reserve = prop->reserve;
    switch (prop->memAttr) {
        case ACL_HBM_MEM_HUGE: {
            rtProp.pg_type = 1UL;
            rtProp.mem_type = 0UL;
            break;
        }
        case ACL_HBM_MEM_NORMAL: {
            rtProp.pg_type = 0UL;
            rtProp.mem_type = 0UL;
            break;
        }
        case ACL_HBM_MEM_HUGE1G: {
            rtProp.pg_type = 2UL; // 1G huge page
            rtProp.mem_type = 0UL;
            break;
        }
        default: {
            ACL_LOG_ERROR("memAttr [%d] support ACL_HBM_MEM_HUGE/ACL_HBM_MEM_NORMAL/ACL_HBM_MEM_HUGE1G. "
                          "Note that ACL_HBM_MEM_HUGE1G is only supported on certain products. "
                          "For details, please refer to the manual.",
                          static_cast<int32_t>(prop->memAttr));
            return ACL_ERROR_INVALID_PARAM;
        }
    }

    const rtError_t rtErr = rtMallocPhysical(reinterpret_cast<rtDrvMemHandle*>(handle), size, &rtProp, flags);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("malloc physical memory failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_PHYSICAL_MEMORY);
    return ACL_SUCCESS;
}

aclError aclrtFreePhysicalImpl(aclrtDrvMemHandle handle)
{
    ACL_ADD_RELEASE_TOTAL_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_PHYSICAL_MEMORY);
    ACL_LOG_DEBUG("start to execute aclrtFreePhysical");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(handle);

    const rtError_t rtErr = rtFreePhysical(reinterpret_cast<rtDrvMemHandle>(handle));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("free physical memory failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_RELEASE_SUCCESS_COUNT(acl::ACL_STATISTICS_MALLOC_FREE_PHYSICAL_MEMORY);
    return ACL_SUCCESS;
}

aclError aclrtMapMemImpl(void *virPtr,
                         size_t size,
                         size_t offset,
                         aclrtDrvMemHandle handle,
                         uint64_t flags)
{
    ACL_ADD_APPLY_TOTAL_COUNT(acl::ACL_STATISTICS_MAP_UNMAP_MEMORY);
    ACL_LOG_DEBUG("start to execute aclrtMapMem, size = %zu, offset = %zu", size, offset);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(virPtr);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(handle);

    if (size == 0UL) {
        ACL_LOG_ERROR("map size must be greater than zero");
        return ACL_ERROR_INVALID_PARAM;
    }
    if (flags != 0UL) {
        ACL_LOG_ERROR("flags must be 0");
        return ACL_ERROR_INVALID_PARAM;
    }

    const rtError_t rtErr = rtMapMem(virPtr, size, offset, reinterpret_cast<rtDrvMemHandle>(handle), flags);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("map memory failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_APPLY_SUCCESS_COUNT(acl::ACL_STATISTICS_MAP_UNMAP_MEMORY);
    return ACL_SUCCESS;
}

aclError aclrtUnmapMemImpl(void *virPtr)
{
    ACL_ADD_RELEASE_TOTAL_COUNT(acl::ACL_STATISTICS_MAP_UNMAP_MEMORY);
    ACL_LOG_DEBUG("start to execute aclrtUnmapMem");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(virPtr);

    const rtError_t rtErr = rtUnmapMem(virPtr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("unmap memory failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    ACL_ADD_RELEASE_SUCCESS_COUNT(acl::ACL_STATISTICS_MAP_UNMAP_MEMORY);
    return ACL_SUCCESS;
}

aclError aclrtMemExportToShareableHandleImpl(aclrtDrvMemHandle handle, aclrtMemHandleType handleType,
                                             uint64_t flags, uint64_t *shareableHandle)
{
  ACL_LOG_DEBUG("start to execute aclrtMemExportToShareableHandle");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(handle);
  ACL_REQUIRES_TRUE(handleType == ACL_MEM_HANDLE_TYPE_NONE, ACL_ERROR_INVALID_PARAM,
                    "handleType in MemExportToShareableHandle must be ACL_MEM_HANDLE_TYPE_NONE !");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(shareableHandle);
  ACL_REQUIRES_TRUE(flags == 0UL, ACL_ERROR_INVALID_PARAM,
                    "flags in MemExportToShareableHandle must be 0 !");

  const rtError_t rtErr = rtMemExportToShareableHandle(reinterpret_cast<rtDrvMemHandle>(handle),
                                                       RT_MEM_HANDLE_TYPE_NONE, flags, shareableHandle);
  if (rtErr != RT_ERROR_NONE) {
    ACL_LOG_CALL_ERROR("export shareable handle failed, runtime result = %d", static_cast<int32_t>(rtErr));
    return ACL_GET_ERRCODE_RTS(rtErr);
  }
  return ACL_SUCCESS;
}

aclError aclrtMemImportFromShareableHandleImpl(uint64_t shareableHandle,
                                               int32_t deviceId, aclrtDrvMemHandle *handle)
{
  ACL_LOG_DEBUG("start to execute aclrtMemImportFromShareableHandle");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(handle);

  const rtError_t rtErr = rtMemImportFromShareableHandle(shareableHandle, deviceId,
                                                         reinterpret_cast<rtDrvMemHandle*>(handle));
  if (rtErr != RT_ERROR_NONE) {
    ACL_LOG_CALL_ERROR("import from shareable handle failed, shareableHandle[%lu], deviceId[%d], runtime result = %d",
                       shareableHandle, deviceId, static_cast<int32_t>(rtErr));
    return ACL_GET_ERRCODE_RTS(rtErr);
  }
  return ACL_SUCCESS;
}

aclError aclrtMemSetPidToShareableHandleImpl(uint64_t shareableHandle, int32_t *pid, size_t pidNum)
{
  ACL_LOG_DEBUG("start to execute aclrtMemSetPidToShareableHandle");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pid);
  ACL_REQUIRES_TRUE(pidNum > 0UL, ACL_ERROR_INVALID_PARAM,
                    "pidNum in SetPidToShareableHandle must be large than 0 !");

  const rtError_t rtErr = rtMemSetPidToShareableHandle(shareableHandle, pid, static_cast<uint32_t>(pidNum));
  if (rtErr != RT_ERROR_NONE) {
    ACL_LOG_CALL_ERROR("set pid to shareable handle failed, shareableHandle[%lu], pidNum[%zu], runtime result = %d",
                       shareableHandle, pidNum, static_cast<int32_t>(rtErr));
    return ACL_GET_ERRCODE_RTS(rtErr);
  }
  return ACL_SUCCESS;
}

aclError aclrtMemGetAllocationGranularityImpl(aclrtPhysicalMemProp *prop, aclrtMemGranularityOptions option,
                                              size_t *granularity)
{
    ACL_LOG_DEBUG("start to execute aclrtMemGetAllocationGranularity");
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(prop);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(granularity);

    rtDrvMemProp_t rtProp1 = {};
    rtProp1.side = prop->location.type;
    rtProp1.devid = prop->location.id;
    rtProp1.module_id = acl::APP_MODE_ID_U16;
    rtProp1.reserve = prop->reserve;
    switch (prop->memAttr) {
        case ACL_HBM_MEM_HUGE: {
            rtProp1.pg_type = 1U;
            rtProp1.mem_type = 0U;
            break;
        }
        case ACL_HBM_MEM_NORMAL: {
            rtProp1.pg_type = 0U;
            rtProp1.mem_type = 0U;
            break;
        }
        case ACL_HBM_MEM_HUGE1G: {
            rtProp1.pg_type = 2UL; // 1G huge page
            rtProp1.mem_type = 0U;
            break;
        }
        default: {
            ACL_LOG_ERROR("memAttr [%d] support ACL_HBM_MEM_HUGE/ACL_HBM_MEM_NORMAL/ACL_HBM_MEM_HUGE1G. "
                          "Note that ACL_HBM_MEM_HUGE1G is only supported on certain products. "
                          "For details, please refer to the manual.",
                static_cast<int32_t>(prop->memAttr));
            return ACL_ERROR_INVALID_PARAM;
        }
    }

    const rtError_t rtErr = rtMemGetAllocationGranularity(&rtProp1,
        static_cast<rtDrvMemGranularityOptions>(option), granularity);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("Get Allocation Granularity failed, runtime result = %d", static_cast<int32_t>(rtErr));
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtDeviceGetBareTgidImpl(int32_t *pid)
{
  ACL_LOG_DEBUG("start to execute aclrtDeviceGetBareTgid");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(pid);

  const rtError_t rtErr = rtDeviceGetBareTgid(reinterpret_cast<uint32_t *>(pid));
  if (rtErr != RT_ERROR_NONE) {
      ACL_LOG_CALL_ERROR("Get Bare Tgid Falied, runtime result = %d", static_cast<int32_t>(rtErr));
      return ACL_GET_ERRCODE_RTS(rtErr);
  }
  return ACL_SUCCESS;
}

aclError aclrtCmoAsyncImpl(void *src, size_t size, aclrtCmoType cmoType, aclrtStream stream)
{
  ACL_LOG_DEBUG("start to execute aclrtCmoAsync");
  ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);
  if (size == 0UL) {
      ACL_LOG_ERROR("size must be greater than zero");
      return ACL_ERROR_INVALID_PARAM;
  }
  ACL_REQUIRES_TRUE(cmoType == ACL_RT_CMO_TYPE_PREFETCH, ACL_ERROR_INVALID_PARAM,
                    "cmoType must be ACL_RT_CMO_TYPE_PREFETCH");
  rtCmoOpCode_t type = RT_CMO_PREFETCH;

  ACL_REQUIRES_CALL_RTS_OK(rtCmoAsync(src, size, type, stream), rtCmoAsync);
  return ACL_SUCCESS;
}

aclError aclrtGetMemcpyDescSizeImpl(aclrtMemcpyKind kind, size_t *descSize)
{
    ACL_LOG_INFO("start to execute aclrtGetMemcpyDescSize");
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(descSize);
    ACL_CHECK_LESS_UINT(static_cast<uint32_t>(kind), static_cast<uint32_t>(RT_MEMCPY_KIND_MAX));
    const auto rt_mem_kind = static_cast<rtMemcpyKind>(static_cast<uint32_t>(kind));
    const auto rtErr = rtsGetMemcpyDescSize(rt_mem_kind, descSize);
    if (rtErr != RT_ERROR_NONE) {
       ACL_LOG_CALL_ERROR("Get memcpy desc size Failed, runtime result = %d", rtErr);
       return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtSetMemcpyDescImpl(void *desc, aclrtMemcpyKind kind, void *srcAddr, void *dstAddr, size_t count,
                                void *config)
{
    ACL_LOG_INFO("start to execute aclrtSetMemcpyDesc");
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(desc);
    ACL_CHECK_LESS_UINT(static_cast<uint32_t>(kind), static_cast<uint32_t>(RT_MEMCPY_KIND_MAX));
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(srcAddr);
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(dstAddr);
    ACL_REQUIRES_POSITIVE_WITH_INPUT_REPORT(count);
    if (config != nullptr) {
        ACL_LOG_ERROR("[Check][config]param is reserved and only support currently nullptr."); \
        return ACL_ERROR_INVALID_PARAM;
    }

    const auto rt_mem_kind = static_cast<rtMemcpyKind>(static_cast<uint32_t>(kind));
    const auto rtErr = rtsSetMemcpyDesc(static_cast<rtMemcpyDesc_t>(desc), rt_mem_kind, srcAddr, dstAddr,
                                        count, nullptr);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("Set memcpy desc Failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtMemcpyAsyncWithDescImpl(void *desc, aclrtMemcpyKind kind, aclrtStream stream)
{
    ACL_LOG_INFO("start to execute aclrtMemcpyAsyncWithDesc");
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(desc);
    ACL_CHECK_LESS_UINT(static_cast<uint32_t>(kind), static_cast<uint32_t>(RT_MEMCPY_KIND_MAX));
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(stream);

    const auto rt_mem_kind = static_cast<rtMemcpyKind>(static_cast<int32_t>(kind));
    const auto rtErr = rtsMemcpyAsyncWithDesc(static_cast<rtMemcpyDesc_t>(desc), rt_mem_kind, nullptr, stream);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("Async memcpy with desc Failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtValueWriteImpl(void* devAddr, uint64_t value, uint32_t flag, aclrtStream stream)
{
    ACL_LOG_INFO("start to execute aclrtValueWrite");
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(devAddr);

    const auto rtErr = rtsValueWrite(devAddr, value, flag, static_cast<rtStream_t>(stream));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsValueWrite Failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtValueWaitImpl(void* devAddr, uint64_t value, uint32_t flag, aclrtStream stream)
{
    ACL_LOG_INFO("start to execute aclrtValueWait");
    ACL_REQUIRES_NOT_NULL_WITH_INNER_REPORT(devAddr);

    const auto rtErr = rtsValueWait(devAddr, value, flag, static_cast<rtStream_t>(stream));
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsValueWait Failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}

aclError aclrtReduceAsyncImpl(void *dst, const void *src, uint64_t count, aclrtReduceKind kind,
    aclDataType type, aclrtStream stream, void *reserve)
{
    ACL_LOG_DEBUG("start to execute aclrtReduceAsync, count = [%lu], kind = [%u], type = [%u]", count,
        static_cast<uint32_t>(kind), static_cast<uint32_t>(type));
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(dst);
    ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(src);
    if (reserve != nullptr) {
        ACL_LOG_ERROR("[Check][reserve]param must be null.");
        acl::AclErrorLogManager::ReportInputError("EH0002", {"param"}, {"reserve"});
        return ACL_ERROR_INVALID_PARAM;
    }

    rtDataType dataType;
    if (kMapDataType.count(type) > 0) {
        dataType = kMapDataType.at(type);
    } else {
        ACL_LOG_ERROR("[Check][param]param type [%d] is invalid.", static_cast<int32_t>(type));
        acl::AclErrorLogManager::ReportInputError(acl::INVALID_PARAM_MSG, {"param"}, {"type"});
        return ACL_ERROR_INVALID_PARAM;
    }

    rtReduceInfo_t reduceInfo;
    reduceInfo.dst = dst;
    reduceInfo.src = const_cast<void*>(src);
    reduceInfo.count = static_cast<size_t>(count);
    reduceInfo.kind = static_cast<rtReduceKind>(kind);
    reduceInfo.type = dataType;
    const rtError_t rtErr = rtsLaunchReduceAsyncTask(&reduceInfo, static_cast<rtStream_t>(stream), reserve);
    if (rtErr != RT_ERROR_NONE) {
        ACL_LOG_CALL_ERROR("call rtsGetThreadLastTaskId failed, runtime result = %d", rtErr);
        return ACL_GET_ERRCODE_RTS(rtErr);
    }
    return ACL_SUCCESS;
}
